/* Tokenizer.cpp
 * Purpose: To split source lines into tokens
 *
 * Description: This class first calls for a line of source code, then splits it into an array of character. It then
 * 				iterates through the char array, examining the characters to decide what kind of token to fetch.
 */
#include <iostream>
#include "Tokenizer.h"
using namespace std;

const string resWords[]= {"DO", "IF", "IN", "OF", "OR", "TO", "AND", "DIV", "END", "FOR", "MOD", "NIL", "NOT", "SET", "VAR", "CASE", "ELSE", "FILE", "GOTO", "THEN", "TYPE", "WITH", "ARRAY", "BEGIN", "CONST", "LABEL", "UNTIL", "WHILE", "DOWNTO", "PACKED", "RECORD", "REPEAT", "PROGRAM", "FUNCTION", "PROCEDURE"};
const string specChars[] = {"^","*","(",")","-","+","=","[","]",":",";","<",">",",",".","/",":=","<=",">=","<>",".."};


// Public Functions:
Tokenizer::Tokenizer(Scanner & scanr) {

	scanner=&scanr;  //this is how we set the private scanner to the scanner passed in.

}

string Tokenizer::GetTokenCode() { return code;}

string Tokenizer::GetTokenString(){ return tokenString;}

Literal* Tokenizer::FetchLiteral() { return lit; }

bool Tokenizer::FetchToken() {

	cout << "Fetching a token...\n";

	char firstChar = scanner->FetchCharacter();

	cout << "Got a character...";

	cout << firstChar << endl;

	if (firstChar == '.' || firstChar == '\n')// || firstChar == 0)
		return false;
	else if (firstChar == ' ')
		SkipBlanks();

	if (isdigit(firstChar) != 0) {
		FetchNumber(firstChar, DIGIT);
		return true;
	}
	else if (firstChar == '\''){
		FetchString(firstChar);
		return true;
	}
	else if (isalpha(firstChar) != 0){
		FetchWord(firstChar, LETTER);
		return true;
	}
	else{
		char ch = scanner->FetchCharacter();
		code = ch + "\t";
		tokenString = ch + "\t";
		return true;
	}
}

// Private Functions:
char Tokenizer::SkipBlanks() {

	cout << "Skipping blanks...\n";
	char blank = scanner->FetchCharacter();
	if (blank != ' ')
		return blank;
	else {
		while(blank == ' ')
			scanner->FetchCharacter();
		return blank;
	}

}

void Tokenizer::FetchWord(char word, CharCode) {

	cout << "Using FetchWord()" << endl;
	string tStr = "\0";
	tokenString = "\0";
	char nextChar = scanner->FetchCharacter();
	tStr = word;

	tokenString.append(tStr);
	tStr = nextChar;
	tokenString.append(tStr);

	while (isalpha(nextChar) != 0) {		//Get the entire word
		nextChar = scanner->FetchCharacter();
		tStr = nextChar;
		tokenString.append(tStr);
	}

	code = "\0";

		for (int i = 0; i < tokenString.length(); i++)
			code += toupper(tokenString.at(i));

	cout << "tokenString after FetchWord: " << tokenString << endl;

}

void Tokenizer::FetchNumber(char num, CharCode) {

	char nextChar;
	tokenString.clear();

	code = "<NUMBER>";
	nextChar = scanner->FetchCharacter();
	while (nextChar != ' ') {
		tokenString += nextChar;
		nextChar = scanner->FetchCharacter();
	}

	/*for(int i = 0; i < length; i++) {	// test for int or real
		if (tStr.at(i) == '.' || tStr.at(i) == 'e')
			code = "REAL";
		else
			code = "INTEGER";
	}
*/

}

void Tokenizer::FetchString(char first) {

	string tStr;
	string ch;
	string delim ("\'");			// Check to make sure this is the actual delimiter
	bool EOS = false;

	while (!EOS) {
		ch = scanner->FetchCharacter();
		if (ch == delim)
			EOS = true;
		else {
			tStr+=(ch);
			EOS = false;
		}
	}
	tokenString = tStr;


}

void Tokenizer::FetchSpecial(char spec) {
/*
	bool isSpecial = false;
	int length = specChars.length();
	for (int i; i < length; i++){
		string ch = spec;
		if (ch.compare(specChars[i]) != 0)
			isSpecial = true;

		}*/
	tokenString = spec;
}

bool Tokenizer::IsReservedWord(string & word) {

	signed int arraySize = ARRAY_SIZE(resWords);
	for (int i = 0; i < arraySize; i++){
			if (word == resWords[i])
				return true;
		}
	return false;

}

Tokenizer::~Tokenizer()
{
}
